package com.baizhi.security;

import com.baizhi.service.IBzAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private IBzAdminService adminService;


    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /**
     * AuthenticationManagerBuilder
     * Authentication 认证  在Shiro和SpringSecurity中所有以Authen开头的单词都和认证有关系
     *
     * 进行认证数据获取
     * 1 默认情况下是假数据 用户名user 密码UUID
     * 2 程序员自己制造假数据
     * 3 获取数据库数据
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * 内存假数据
         */
//        auth.inMemoryAuthentication()
//                .withUser("zhangsan")
////                默认情况 SpringSecurity所有的密码都是加密校验
////                如果不想密码加密 需要给密码添加前缀 {noop}
//                .password("$2a$10$jbV4mKV1c8L.mnztYXwQleijWFrMihSr/OhIe3nDn8Lh6kQ3Vn2r6")
////                和授权相关 authorities 给当前用户声明假的授权数据
////                给zhangsan声明角色需要前缀 ROLE_
//                .authorities("ROLE_ADMIN","sys:admin:add","sys:admin:delete")
//        .and()
//                .withUser("lisi")
//                .password("$2a$10$jbV4mKV1c8L.mnztYXwQleijWFrMihSr/OhIe3nDn8Lh6kQ3Vn2r6")
////                和授权相关 authorities 给当前用户声明假的授权数据
////                给zhangsan声明角色需要前缀 ROLE_
//                .authorities("ROLE_SUPERADMIN","sys:ztree:select");

//        /**
//         * 查询数据库数据
//         * 登陆方法是SpringSecurity实现的，逻辑我们改不了
//         *
//         * 参数是一个业务类
//         */
        auth.userDetailsService(adminService)
                .passwordEncoder(bCryptPasswordEncoder());

    }

    /**
     * HttpSecurity
     *
     * 配置认证规则
     * 1 拦截规则
     * 2 认证的相关路径 认证方法地址 认证成功要跳转的地址 认证失败要跳转地址等等
     * 3 添加自定义过滤器
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        默认情况下 拦截规则是全部拦截
//        authorizeRequests
//        authorization 授权 在Shiro和SpringSecurity中所有以author开头的单词都和授权有关系
        http.authorizeRequests()
//                配置不拦截 permitAll
                .antMatchers(
                        "/admin/**",
                        "/img/**",
                        "/css/**",
                        "/js/**",
                        "/ztree/**",
                        "/login.jsp",
                        "/login",
                        "/layui/**")
                .permitAll()
//                具有admin的角色才能访问/menu/selectMenuListBySql 接口
//                .antMatchers("/menu/selectMenuListBySql").hasRole("ADMIN")
////                具有sys:ztree:select才能欧访问该接口
//                .antMatchers("/menu/getZtreeNodes").hasAuthority("sys:ztree:select")
//                除了不拦截路径其他路径都拦截 anyRequest 所有请求都需要认证
        .anyRequest().authenticated();

//        formLogin 自定义表单登陆的所有内容
        http.formLogin()
//                自定义登陆页面
                .loginPage("/login.jsp")
//                失败跳转的地址
                .failureForwardUrl("/admin/failureRedirectUrl")
//                成功跳转的地址
                .successForwardUrl("/admin/successRedirectUrl")
//                loginProcessingUrl 登陆方法的地址 登陆方法的地址固定是/login
//                该地址对应的接口是SpringSecurity实现的登陆方法
                .loginProcessingUrl("/login")
                .and()
                .csrf()
                .disable();
//        关闭iframe禁用
        http.headers().frameOptions().disable();
    }
}
